<?
    /* -*- Mode: PHP5; tab-width: 4; indent-tabs-mode: nil; basic-offset: 4 -*- */

    /*********************************************************
    *            --== InArch ==--
    *
    * UnitTest Initialization Framework Class. The main purpose of
    * this class is to prepare the PEAR Unit Test framework and
    * to perform the actual test upon request. 
    * 
    * Depends on the definition of the constant INA_ROOT
    *
    * @author Kulikov Alexey <a.kulikov@gmail.com>
    * @version n/a
    * @since 19.04.2005
    * @copyright essentialmind.com 2005
    *
    *********************************************************/
    
    
    /***
    * Class unitTest
    ****
    * This class initializes the unit test framework of PEAR
    * unit test package and loads an instance of a class to test
    * and its test suite and then performs the unit test
    * outputting results to the browser.
    * 
    * <code>
    *   $myTest = new unitTest('foo');
    *   echo $myTest->run();
    * </code>
    * 
    * In the above example it is assumed that there is a file
    * called foo.class.php found in the INA classes folder and
    * a file fooTest.class.php found in the INA unitTests folder
    * 
    * It is important to note, that according to Pear's unit test
    * package the test class must be named exactly as the class to
    * be tested with Test appended to its name, for example the class
    * 
    * class foo{}
    * 
    * will have a test class named
    * 
    * class fooTest{}
    ****
    * @package PHPUnitTest
    * @author A Kulikov <a.kulikov@gmail.com>
    * @version n/a
    * @since 19.04.2005
    * @copyright essentialmind.com 2005
    *
    * @see http://developer.essentialmind.com/wiki/INA/guides/code/tips#h29-4
    ***/
    class unitTest{
        //name of the class to test
        private $className;
        
        //actual class file location
        private $classFile;
        
        //test suite file location
        private $classTestFile;
        
        
        ##### path related settings #####
        #
        //folder where classes reside
        protected $classFolder;
        
        //folder where unit test suites reside
        protected $classTestFolder;
        
        //extension of class name
        protected $classExtention;
        
        //extentions of unit test suite class
        protected $classTestExtension;
        
        //place where PHPUnit is located
        protected $phpUnitFolder;
        #
        #####
        
    
        /**
         * unitTest::__construct()
         * 
         * Constructor. It checks whether the neccessary files
         * exists, and if so sets the neccessary paths and data
         * 
         * @param string $name  - name of the class to test
         * @return void
         **/
        function __construct($name){
            
            //bogus check whether the files exist
            try{
                //prepare the paths
                $this->setPHPUnitFolder(INA_ROOT.'lib'.DIRECTORY_SEPARATOR.'PHPUnit'.DIRECTORY_SEPARATOR);
                $this->setClassFolder(INA_ROOT.'classes'.DIRECTORY_SEPARATOR);
                $this->setClassTestFolder(INA_ROOT.'unitTests'.DIRECTORY_SEPARATOR);
                
                //prepare file extensions
                $this->setClassExtension('.class.php');
                $this->setClassTestExtension('Test.class.php');
                
                //set the name of the class in need for a test
                $this->setClassName($name);
                
                //check if the class exists
                if(!file_exists($this->getClass())){
                    throw new Exception('The class "' . $name . '" does not exist, thus it can not be unit tested!',1);
                }
                
                //check if the Unit Test Case exists
                if(!file_exists($this->getTestClass())){
                    throw new Exception('A Unit test case for the class "' . $name . '" does not exist!',2);
                }
                
                //check if the PHPUnit package is present
                if(!file_exists($this->getPHPUnitFolder().'PHPUnit.php')){
                    throw new Exception('The PEAR PHP Unit Test Suite was not found! Please install!',3);
                }
                
            }catch(exception $e){ //something went wrong
                echo 'INA Unit Test Exception: ',  $e->getMessage(), "\n";
                exit;
            }
        }
        
        
        /**
         * unitTest::setClassName()
         * 
         * sets the name of the class to test
         *  
         * @param $name
         * @return void
         **/
        function setClassName($name){
            $this->name = $name;
        }
        
        
        /**
         * unitTest::getClassName()
         * 
         * returns the name of the class to test
         * 
         * @return string
         **/
        function getClassName(){
            return $this->name;
        }
        
        
        /**
         * unitTest::run()
         * 
         * performs the actual unit test and outputs results to the browser
         * 
         * @return string 
         **/
        function run(){
            //all bogus checks are fine, thus initialize the unit test framework
            require_once $this->getPHPUnitFolder().'PHPUnit.php';
            require_once $this->getClass();
            require_once $this->getTestClass();
            
            //run the test
            $suite  = new PHPUnit_TestSuite($this->getClassName().'Test');
            $result = PHPUnit::run($suite);

            //return the test result
            return $result->toHTML();
        }
        
        
        /**
         * unitTest::setClassFolder()
         * 
         * sets the folder where the normal classes are located
         * 
         * @param string $folder
         * @return void
         **/
        function setClassFolder($folder){
            if(is_dir($folder)){
                $this->classFolder = $folder;
                return true;
            }
            
            throw new Exception('The Class Directory was not found!');
        }
        
        
        /**
         * unitTest::setClassTestFolder()
         * 
         * sets the folder where the test classes are located
         * 
         * @param string $folder
         * @return bool
         **/
        function setClassTestFolder($folder){
            if(is_dir($folder)){
                $this->classTestFolder = $folder;
                return true;
            }
            
            throw new Exception('The Class Test Directory was not found!');
        }
        
        
        /**
         * unitTest::setClassExtension()
         * 
         * sets the file extension for normal files
         * 
         * @param string $extension
         * @return void 
         **/
        function setClassExtension($extension){
            $this->classExtension = $extension;
        }
        
        
        /**
         * unitTest::setClassTestExtension()
         * 
         * sets the file extension for the test suite classes
         * 
         * @param string $extension
         * @return void 
         **/
        function setClassTestExtension($extension){
            $this->classTestExtension = $extension;
        }
        
        
        /**
         * unitTest::getClassFolder()
         * 
         * returns the location of the class folder
         * 
         * @return string 
         **/
        function getClassFolder(){
            return $this->classFolder;
        }
        
        
        /**
         * unitTest::getClassTestFolder()
         * 
         * returns the localtion of the test suite folder
         * 
         * @return string 
         **/
        function getClassTestFolder(){
            return $this->classTestFolder;
        }
        
        
        /**
         * unitTest::getClassExtension()
         * 
         * returns the file extention for class files
         * 
         * @return string 
         **/
        function getClassExtension(){
            return $this->classExtension;
        }
        
        
        /**
         * unitTest::getClassTestExtension()
         * 
         * returns the file extension for test class suite files
         * 
         * @return string 
         **/
        function getClassTestExtension(){
            return $this->classTestExtension;
        }
        
        
        /**
         * unitTest::getClass()
         * 
         * returns a full path to the class that needs testing
         * 
         * @return string 
         **/
        protected function getClass(){
            return $this->getClassFolder() . $this->getClassName() . $this->getClassExtension();
        }
        
        
        /**
         * unitTest::getTestClass()
         * 
         * returns a full path to the test suite for the class that needs testing
         * 
         * @return string 
         **/
        protected function getTestClass(){
            return $this->getClassTestFolder() . $this->getClassName() . $this->getClassTestExtension();
        }
        
        
        /**
         * unitTest::setPHPUnitFolder()
         * 
         * Sets the localtion where the PearUnit test framework
         * is located
         * 
         * @param string $folder
         * @return bool
         **/
        function setPHPUnitFolder($folder){
            if(is_dir($folder)){
                $this->phpUnitFolder = $folder;
                return true;
            }
            
            throw new Exception('The PHPUnitTest directory was not found!');
        }
        
        
        /**
         * unitTest::getPHPUnitFolder()
         * 
         * Returns the current path to the PearUnit test framework
         * 
         * @return string
         **/
        function getPHPUnitFolder(){
            return $this->phpUnitFolder;
        }
    }
?>